package com.efounder.common.floatwindow;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.os.Build;
import androidx.core.view.ViewConfigurationCompat;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;

import com.efounder.util.AppContext;
import com.utilcode.util.ActivityUtils;
import com.utilcode.util.LogUtils;
import com.utilcode.util.ScreenUtils;

/**
 * 应用悬浮窗
 *
 * @autor yqs
 * @date 2019/5/13 15:48
 **/
public class FloatWindowImpl implements IFloatWindow {

    private Context mContext;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams wmParams;
    //自定义的view
    private IFloatView floatView;
    private ValueAnimator mAnimator;
    private TimeInterpolator mDecelerateInterpolator;
    private float downX;
    private float downY;
    private float upX;
    private float upY;
    private boolean mClick = false;
    //触发移动事件的最小距离
    private int mSlop;

    //默认的距离两边的偏移
    private int defalutXOffset = 5;

    //悬浮窗view 最初的xy 偏移
    private int startXoffset;
    private int startYoffset;


    public FloatWindowImpl(IFloatView floatView) {
        mContext = ActivityUtils.getTopActivity();
        this.floatView = floatView;
        mWindowManager = getWindowManager();
        setFloatWindow();
        initTouchEvent();
    }

    @Override
    public void show() {
        if (isShowing()) {
            return;
        }
        floatView.getView().setVisibility(View.VISIBLE);
    }

    @Override
    public void hide() {
        floatView.getView().setVisibility(View.GONE);
    }

    @Override
    public boolean isShowing() {
        return floatView.getView().getVisibility() == View.VISIBLE;
    }

    @Override
    public View getView() {
        return floatView.getView();
    }


    /**
     * 创建一个小悬浮窗。初始位置为屏幕的右下角位置。
     */
    public void setFloatWindow() {
        wmParams = new WindowManager.LayoutParams();


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            /*android8.TYPE_APPLICATION_OVERLAY*/
            wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            /*android7.0不能用TYPE_TOAST*/
            wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        } else { /*以下代码块使得android6.0之后的用户不必再去手动开启悬浮窗权限*/
            String packname = mContext.getPackageName();
            PackageManager pm = mContext.getPackageManager();
            boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.SYSTEM_ALERT_WINDOW", packname));
            if (permission) {
                wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            } else {
                wmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
            }
        }

        //设置图片格式，效果为背景透明
        wmParams.format = PixelFormat.RGBA_8888;
        //设置浮动窗口不可聚焦（实现操作除浮动窗口外的其他可见窗口的操作）
        wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

//        if (floatView.getGravity() != 0) {
//            wmParams.gravity = floatView.getGravity();
//        } else {
        //调整悬浮窗显示的右侧居中
        wmParams.gravity = Gravity.END | Gravity.CENTER_VERTICAL;

        // }

//        DisplayMetrics dm = new DisplayMetrics();
//        //取得窗口属性
//        mWindowManager.getDefaultDisplay().getMetrics(dm);
//        //窗口的宽度
//        int screenWidth = dm.widthPixels;
//        //窗口高度
//        int screenHeight = dm.heightPixels;
        //以屏幕左上角为原点，设置x、y初始值，相对于gravity
        if (floatView.getXoffset() == 0) {
            floatView.setXoffset(defalutXOffset);
            wmParams.x = defalutXOffset;
        } else {
            wmParams.x = floatView.getXoffset();
            defalutXOffset = floatView.getXoffset();
        }
        wmParams.y = floatView.getYoffset();

        startXoffset = floatView.getXoffset();
        startYoffset = floatView.getYoffset();

        //设置悬浮窗口长宽数据
        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

        floatView.getView().setLayoutParams(wmParams);
        mWindowManager.addView(floatView.getView(), wmParams);
        //触发移动事件的最小距离
        mSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(ViewConfiguration.get(mContext));
    }

    /**
     * 返回当前已创建的WindowManager。
     */
    private WindowManager getWindowManager() {
        if (mWindowManager == null) {
            mWindowManager = (WindowManager) AppContext.getInstance().getSystemService(Context.WINDOW_SERVICE);
        }
        return mWindowManager;
    }


    private void initTouchEvent() {
        switch (floatView.getMoveType()) {
            case MoveType.inactive:
                //位置不可变
                break;
            default:
                getView().setOnTouchListener(new View.OnTouchListener() {
                    float lastX, lastY, changeX, changeY;
                    int newX, newY;

                    @SuppressLint("ClickableViewAccessibility")
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {

                        switch (event.getAction()) {
                            case MotionEvent.ACTION_DOWN:
                                downX = event.getRawX();
                                downY = event.getRawY();
                                lastX = event.getRawX();
                                lastY = event.getRawY();
                                cancelAnimator();
                                break;
                            case MotionEvent.ACTION_MOVE:
                                changeX = event.getRawX() - lastX;
                                changeY = event.getRawY() - lastY;
                                //x 的位置按钮默认显示在右侧，要用 -  显示左侧 用+
                                newX = (int) (floatView.getXoffset() - changeX);
                                newY = (int) (floatView.getYoffset() + changeY);

//                                LogUtils.e("Xoffset=" + floatView.getXoffset(),
//                                        "Yoffset=" + floatView.getYoffset(),
//                                        "x=" + newX, "y=" + newY);
                                updateXY(newX, newY);

                                lastX = event.getRawX();
                                lastY = event.getRawY();
                                break;
                            case MotionEvent.ACTION_UP:
                                upX = event.getRawX();
                                upY = event.getRawY();
                                mClick = (Math.abs(upX - downX) > mSlop) || (Math.abs(upY - downY) > mSlop);
                                switch (floatView.getMoveType()) {
                                    case MoveType.slide:
                                        //释放后自动贴边
                                        int startX = floatView.getXoffset();
                                        int endX = (Math.abs(startX) + v.getWidth() > ScreenUtils.getScreenWidth() / 2 ?
                                                ScreenUtils.getScreenWidth() - v.getWidth() - defalutXOffset :
                                                defalutXOffset);
                                        LogUtils.e("startX=" + startX, "endX=" + endX);
                                        mAnimator = ObjectAnimator.ofInt(startX, endX);
                                        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                            @Override
                                            public void onAnimationUpdate(ValueAnimator animation) {
                                                int x = (int) animation.getAnimatedValue();
                                                updateX(x);
                                            }
                                        });
                                        startAnimator();
                                        break;
                                    case MoveType.back:
                                        //释放后从当前新的偏移回到原来最初开始位置
                                        PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("x", (int) floatView.getXoffset(), startXoffset);
                                        PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("y", (int) floatView.getYoffset(), startYoffset);
                                        mAnimator = ObjectAnimator.ofPropertyValuesHolder(pvhX, pvhY);
                                        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                            @Override
                                            public void onAnimationUpdate(ValueAnimator animation) {
                                                int x = (int) animation.getAnimatedValue("x");
                                                int y = (int) animation.getAnimatedValue("y");
                                                updateXY(x, y);
                                            }
                                        });
                                        startAnimator();
                                        break;
                                    default:
                                        break;
                                }
                                break;
                            default:
                                break;
                        }
                        return mClick;
                    }
                });
        }
    }


    private void startAnimator() {

        if (mDecelerateInterpolator == null) {
            mDecelerateInterpolator = new DecelerateInterpolator();
        }

        mAnimator.setInterpolator(mDecelerateInterpolator);
        mAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimator.removeAllUpdateListeners();
                mAnimator.removeAllListeners();
                mAnimator = null;
            }
        });
        mAnimator.setDuration(300).start();
    }

    private void cancelAnimator() {
        if (mAnimator != null && mAnimator.isRunning()) {
            mAnimator.cancel();
        }
    }


    public void updateXY(int x, int y) {
        wmParams.x = x;
        wmParams.y = y;
        floatView.setXoffset(x);
        floatView.setYoffset(y);
        mWindowManager.updateViewLayout(floatView.getView(), wmParams);
    }

    void updateX(int x) {
        wmParams.x = x;
        floatView.setXoffset(x);
        mWindowManager.updateViewLayout(floatView.getView(), wmParams);
    }

    void updateY(int y) {
        wmParams.y = y;
        floatView.setYoffset(y);
        mWindowManager.updateViewLayout(floatView.getView(), wmParams);
    }
}
